package com.antwork.common.web.jsp;

import com.antwork.common.entity.Pagination;
import com.antwork.common.util.StringUtility;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;

public class TableTag extends AbstractTag {
	private static final long serialVersionUID = -4956591837254227065L;
	private static HashMap<String, TableConfig> tableConfigMap = new HashMap();
	private String name;
	private Pagination<?> pagination = null;
	private String contextPath;

	public void setName(String name) {
		this.name = name;
	}

	public int doStartTag() throws JspException {
		HttpServletRequest request = (HttpServletRequest) this.pageContext
				.getRequest();
		this.contextPath = request.getContextPath();
		this.pagination = ((Pagination) request.getAttribute("pagination"));
		TableConfig tableConfig = (TableConfig) tableConfigMap.get(this.name);
		if (tableConfig == null) {
			try {
				tableConfig = loadTableConfig();
			} catch (Exception e) {
				throw new JspException(e);
			}
			tableConfigMap.put(this.name, tableConfig);
		}

		StringBuffer scriptBuf = new StringBuffer();
		StringBuffer htmlStr = new StringBuffer(
				"<table class=\"table table-bordered table-hover\">");

		htmlStr.append("<thead>");
		htmlStr.append("<tr>");
		String[] head = tableConfig.getHead();
		int tableColumnCount = head.length;
		for (int i = 0; i < head.length; ++i) {
			htmlStr.append("<th>");
			htmlStr.append(head[i]);
			htmlStr.append("</th>");
		}
		String opername = tableConfig.getOpername();
		if (opername != null) {
			htmlStr.append("<th>");
			htmlStr.append(opername);
			htmlStr.append("</th>");
			++tableColumnCount;
		}
		htmlStr.append("</tr>");
		htmlStr.append("</thead>");

		htmlStr.append("<tbody>");
		List list = this.pagination.getResult();
		String[] fieldName = tableConfig.getField();
		int[] textLimit = tableConfig.getTextLimit();
		String[] width = tableConfig.getWidth();
		String onclickField = tableConfig.getOnclickField();
		String onclickHref = tableConfig.getOnclickHref();
		if ((list == null) || (list.size() == 0))
			htmlStr.append("<td colspan=\"" + tableColumnCount
					+ "\">û�м�¼</td>");
		else {
			for (Iterator localIterator = list.iterator(); localIterator
					.hasNext();) {
				Object obj = localIterator.next();
				Field[] fields = obj.getClass().getDeclaredFields();
				Field.setAccessible(fields, true);
				htmlStr.append("<tr>");
				for (int i = 0; i < fieldName.length; ++i) {
					try {
						if (width[i].equals(""))
							htmlStr.append("<td>");
						else {
							htmlStr.append("<td style=\"width:" + width[i]
									+ "\">");
						}
						htmlStr.append(getFieldDisplayValue(tableConfig, obj,
								fields, fieldName[i], textLimit[i],
								onclickField, onclickHref, scriptBuf));
						htmlStr.append("</td>");
					} catch (Exception e) {
						throw new JspException(e);
					}
				}
				String[][] opertype = tableConfig.getOpertype();
				if (opertype != null) {
					htmlStr.append("<td>");
					for (int i = 0; i < opertype.length; ++i) {
						try {
							htmlStr.append(getOpertypeHref(obj, fields,
									opertype[i][0], opertype[i][1]));
							htmlStr.append("   ");
						} catch (Exception e) {
							throw new JspException(e);
						}
					}
					htmlStr.append("</td>");
				}
				htmlStr.append("</tr>");
			}

		}
		htmlStr.append("</tbody>");
		htmlStr.append("</table>");

		String scriptStr = scriptBuf.toString();
		if (!scriptStr.equals("")) {
			htmlStr.append("<script>");
			htmlStr.append(scriptStr);
			htmlStr.append("</script>");
		}

		JspWriter writer = this.pageContext.getOut();
		try {
			writer.write(htmlStr.toString());
		} catch (IOException e) {
			throw new JspException(e);
		}

		return 6;
	}

	public int doEndTag() throws JspException {
		return 6;
	}

	private TableConfig loadTableConfig() throws Exception {
		String configName = "/page-" + this.name + ".properties";
		Properties prop = new Properties();
		try {
			InputStream is = TableTag.class.getResourceAsStream(configName);

			prop.load(is);
		} catch (Throwable e) {
			throw new RuntimeException("table-config file cannot be load: "
					+ configName);
		}
		try {
			// Properties prop = null;
			TableConfig tableConfig = new TableConfig();
			String fieldStr = (String) prop.get("table.field");
			String[] fs = fieldStr.split(";");
			String[] head = new String[fs.length];
			String[] field = new String[fs.length];
			int[] textLimit = new int[fs.length];
			String[] width = new String[fs.length];
			for (int i = 0; i < fs.length; ++i) {
				String[] f = fs[i].split("\\|");
				if (f.length == 3) {
					head[i] = f[1];
					field[i] = f[0];
					textLimit[i] = Integer.parseInt(f[2]);
					width[i] = "";
				} else if (f.length == 4) {
					head[i] = f[1];
					field[i] = f[0];
					textLimit[i] = Integer.parseInt(f[2]);
					width[i] = f[3];
				} else {
					head[i] = f[1];
					field[i] = f[0];
					textLimit[i] = 0;
					width[i] = "";
				}
			}
			tableConfig.setHead(head);
			tableConfig.setField(field);
			tableConfig.setTextLimit(textLimit);
			tableConfig.setWidth(width);
			String onclickStr = (String) prop.get("table.onclick");
			if ((onclickStr != null) && (!onclickStr.equals(""))) {
				String[] onclick = onclickStr.split("\\|");
				tableConfig.setOnclickField(onclick[0]);
				tableConfig.setOnclickHref(onclick[1]);
			}
			String opername = (String) prop.get("table.opername");
			if ((opername != null) && (!opername.equals(""))) {
				tableConfig.setOpername(opername);
				String opertypeStr = (String) prop.get("table.opertype");
				String[] oper = opertypeStr.split(";");
				String[][] opertype = new String[oper.length][2];
				for (int i = 0; i < oper.length; ++i) {
					String[] o = oper[i].split("\\|");
					opertype[i][0] = o[0];
					opertype[i][1] = o[1];
				}
				tableConfig.setOpertype(opertype);
			}
			String fieldtypeStr = (String) prop.get("table.fieldexpand");
			if ((fieldtypeStr != null) && (!fieldtypeStr.equals(""))) {
				String[] fts = fieldtypeStr.split(";");
				for (int i = 0; i < fts.length; ++i) {
					String[] ft = fts[i].split("=");
					tableConfig.setFieldexpand(ft[0], ft[1]);
				}
			}
			String fieldpopoverStr = (String) prop.get("table.fieldpopover");
			if ((fieldpopoverStr != null) && (!fieldpopoverStr.equals(""))) {
				String[] fps = fieldpopoverStr.split(";");
				for (int i = 0; i < fps.length; ++i) {
					String[] ft = fps[i].split("=");
					tableConfig.putFieldpopover(ft[0], ft[1]);
				}
			}
			return tableConfig;
		} catch (Exception e) {
			throw new Exception("Parse " + configName + " error! "
					+ e.getMessage());
		}
	}

	private String getFieldDisplayValue(TableConfig tableConfig, Object bean,
			Field[] fields, String fieldName, int textlimit,
			String onlickField, String onclickHref, StringBuffer scriptBuf)
			throws Exception {
		String value = getFieldValue(bean, fields, fieldName);
		if (textlimit > 0) {
			value = StringUtility.getMoreString(value, textlimit, null);
			String fieldpopover = tableConfig.getFieldpopover(fieldName);
			if ((fieldpopover != null) && (value.indexOf("...") != -1)) {
				if (fieldpopover.indexOf("#") != -1) {
					int times = 0;
					do {
						++times;
						String conditionField = fieldpopover.substring(
								fieldpopover.indexOf("#") + 1,
								fieldpopover.length());
						conditionField = conditionField.substring(0,
								conditionField.indexOf("#"));
						String conditionValue = getFieldValue(bean, fields,
								conditionField);
						fieldpopover = fieldpopover.replace("#"
								+ conditionField + "#", conditionValue);
					} while ((fieldpopover.indexOf("#") != -1) && (times <= 20));
				}

				String uuid = StringUtility.generateUUID();
				value = value + "<i id=\"" + uuid
						+ "\" class=\"icon-list-alt\">";
				scriptBuf.append("$(\"#" + uuid + "\").popover(" + fieldpopover
						+ ");");
			}
		}
		if (fieldName.equals(onlickField))
			if (onclickHref.indexOf("#") != -1) {
				int times = 0;
				do {
					++times;
					String conditionField = onclickHref.substring(
							onclickHref.indexOf("#") + 1, onclickHref.length());
					conditionField = conditionField.substring(0,
							conditionField.indexOf("#"));
					String conditionValue = getFieldValue(bean, fields,
							conditionField);
					onclickHref = onclickHref.replace("#" + conditionField
							+ "#", conditionValue);
				} while ((onclickHref.indexOf("#") != -1) && (times <= 20));

				if (onclickHref.indexOf("javascript") != -1)
					onclickHref = "<a href=\"" + onclickHref + "\">" + value
							+ "</a>";
				else {
					onclickHref = "<a href=" + this.contextPath + onclickHref
							+ ">" + value + "</a>";
				}
				value = onclickHref;
			} else {
				value = onclickHref;
			}
		else {
			value = tableConfig.getFieldExpand(fieldName, value);
		}
		return value;
	}

	private String getFieldValue(Object bean, Field[] fields, String fieldName)
			throws Exception {
		if (bean instanceof HashMap) {
			HashMap map = (HashMap) bean;
			Object o = map.get(fieldName);
			if (o == null) {
				return "";
			}
			return o.toString();
		}

		Field.setAccessible(fields, true);
		for (int i = 0; i < fields.length; ++i) {
			String fname = fields[i].getName();
			if (fieldName.equals(fname)) {
				Object v = fields[i].get(bean);
				if (v == null) {
					return "";
				}
				return v.toString();
			}

		}

		return "";
	}

	private String getOpertypeHref(Object bean, Field[] fields,
			String opertypeName, String opertypeHref) throws Exception {
		if (opertypeHref.indexOf("#") != -1) {
			int times = 0;
			do {
				++times;
				String conditionField = opertypeHref.substring(
						opertypeHref.indexOf("#") + 1, opertypeHref.length());
				conditionField = conditionField.substring(0,
						conditionField.indexOf("#"));
				String conditionValue = getFieldValue(bean, fields,
						conditionField);

				opertypeHref = opertypeHref.replace("#" + conditionField + "#",
						conditionValue);
			} while ((opertypeHref.indexOf("#") != -1) && (times <= 20));

			if (opertypeHref.indexOf("javascript") != -1)
				opertypeHref = "<a href=\"" + opertypeHref + "\">"
						+ opertypeName + "</a>";
			else {
				opertypeHref = "<a href=" + this.contextPath + opertypeHref
						+ ">" + opertypeName + "</a>";
			}

			return opertypeHref;
		}
		return opertypeHref;
	}
}